﻿/*
 * ©Soft Sorjan 2012, All rights reserverd
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Lidgren.Network;
using Microsoft.Xna.Framework;

namespace Erebos
{
    enum VariableType
    {
        Byte,
        String,
        Integer
    }

    class SendCollection<T, T2>
    {
        private List<T> _list1;
        private List<T2> _list2;

        public SendCollection()
        {
            _list1 = new List<T>();
            _list2 = new List<T2>();
        }

        public void Add(T key, T2 value)
        {
            _list1.Add(key);
            _list2.Add(value);
        }

        public KeyValuePair<T, T2>[] ToArray()
        {
            KeyValuePair<T, T2>[] array = new KeyValuePair<T, T2>[_list1.Count];
            for (int i = 0; i < _list1.Count; i++)
            {
                KeyValuePair<T, T2> kvp = new KeyValuePair<T, T2>(_list1[i], _list2[i]);
                array[i] = kvp;
            }
            return array;
        }
    }

    public delegate void OnIncomingMessageEvent(NetIncomingMessage message);

    class ClientHandler
    {
        private static NetClient _client;
        private static bool _running;
        private static Dictionary<byte, OnIncomingMessageEvent> _events = new Dictionary<byte, OnIncomingMessageEvent>();

        public static void Connect()
        {
            NetPeerConfiguration conf = new NetPeerConfiguration("abc123def456");
            conf.EnableMessageType(NetIncomingMessageType.DiscoveryRequest);
            _client = new NetClient(conf);
            _client.Start();
            _client.DiscoverKnownPeer("127.0.0.1", 8888);
            _client.Connect("127.0.0.1", 8888);
            _running = true;
        }

        public static void AddHandle(byte key, OnIncomingMessageEvent value)
        {
            if (_events.ContainsKey(key))
                _events[key] = value;
            else
                _events.Add(key, value);
        }

        public static void RemoveHandle(byte key)
        {
            _events.Remove(key);
        }

        public static void Send(SendCollection<object, VariableType> collection, NetDeliveryMethod method)
        {
            NetOutgoingMessage message = _client.CreateMessage();
            foreach(KeyValuePair<object, VariableType> kvp in collection.ToArray())
            {
                switch (kvp.Value)
                {
                    case VariableType.Byte:
                        message.Write((byte)kvp.Key);
                        break;
                    case VariableType.Integer:
                        message.Write((int)kvp.Key);
                        break;
                    case VariableType.String:
                        message.Write((string)kvp.Key);
                        break;
                }
            }
            _client.SendMessage(message, method);
        }

        public static void Update(GameTime gameTime)
        {
            if (_running)
            {
                if (_client.ConnectionStatus == NetConnectionStatus.Disconnected)
                {
                    //MainGame.SetScreen(new ConnectionLostScreenFiles.ConnectionLostScreen());
                    Close();
                }

                NetIncomingMessage msg;
                if ((msg = _client.ReadMessage()) != null)
                {
                    switch (msg.MessageType)
                    {
                        case NetIncomingMessageType.Data:
                            byte protocol = msg.ReadByte();

                            if (_events.ContainsKey(protocol))
                                _events[protocol](msg);
                            else
                                Console.WriteLine("Unknow Protocol '" + protocol + "'");
                            break;
                    }
                }
            }
        }

        public static void Close()
        {
            _client.Disconnect("");
            _client.Shutdown("");
            _running = false;
        }
    }
}
